package com.yc.cloud.admin.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yc.cloud.admin.dto.HwRegionNode;
import com.yc.cloud.admin.dto.request.HwRegionCreateReqDTO;
import com.yc.cloud.admin.dto.request.HwRegionQueryReqDTO;
import com.yc.cloud.admin.dto.request.HwRegionUpdateReqDTO;
import com.yc.cloud.admin.service.HwRegionService;
import com.yc.cloud.admin.vo.HwRegionVo;
import com.yc.cloud.api.constants.SystemConfigConstants;
import com.yc.cloud.common.orm.CommonPage;
import com.yc.cloud.entity.HwRegion;
import com.yc.cloud.mapper.HwRegionMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 硬件区域管理表 服务实现类
 * </p>
 *
 * @author kinggu
 * @since 2025-09-29
 */
@Slf4j
@Service
public class HwRegionServiceImpl extends ServiceImpl<HwRegionMapper, HwRegion> implements HwRegionService {

    @Resource
    private HwRegionMapper hwRegionMapper;
    
    @Resource
    private com.yc.cloud.admin.service.HwMonitoringPointService hwMonitoringPointService;

    @Override
    public HwRegionVo create(HwRegionCreateReqDTO createReqDTO) {
        HwRegion hwRegion = new HwRegion();
        BeanUtils.copyProperties(createReqDTO, hwRegion);
        
        // 设置level（如果有父级，自动计算level）
        if (createReqDTO.getParentId() != null && createReqDTO.getParentId() > 0) {
            HwRegion parent = hwRegionMapper.selectById(createReqDTO.getParentId());
            if (parent != null) {
                hwRegion.setLevel(parent.getLevel() + 1);
            }
        }
        
        hwRegionMapper.insert(hwRegion);
        return convertToVo(hwRegion);
    }

    @Override
    public HwRegionVo update(HwRegionUpdateReqDTO updateReqDTO) {
        HwRegion hwRegion = hwRegionMapper.selectById(updateReqDTO.getId());
        if (hwRegion == null) {
            return null;
        }
        
        BeanUtils.copyProperties(updateReqDTO, hwRegion);
        
        // 更新level（如果父级改变，重新计算level）
        if (updateReqDTO.getParentId() != null && updateReqDTO.getParentId() > 0) {
            HwRegion parent = hwRegionMapper.selectById(updateReqDTO.getParentId());
            if (parent != null) {
                hwRegion.setLevel(parent.getLevel() + 1);
            }
        } else {
            hwRegion.setLevel(1); // 根节点
        }
        
        hwRegionMapper.updateById(hwRegion);
        return convertToVo(hwRegion);
    }

    @Override
    public boolean delete(Long id) {
        HwRegion hwRegion = hwRegionMapper.selectById(id);
        if (hwRegion == null) {
            return false;
        }
        
        // 检查是否有子区域
        QueryWrapper<HwRegion> query = new QueryWrapper<>();
        query.eq(HwRegion.ParentId, id)
             .eq(HwRegion.IsDeleted, SystemConfigConstants.NOT_DELETED);
        long childCount = hwRegionMapper.selectCount(query);
        
        if (childCount > 0) {
            throw new RuntimeException("该区域下还有子区域，无法删除");
        }
        
        // 逻辑删除
        hwRegion.setIsDeleted(SystemConfigConstants.DELETED.byteValue());
        return hwRegionMapper.updateById(hwRegion) > 0;
    }

    @Override
    public HwRegionVo getVOById(Long id) {
        HwRegion hwRegion = hwRegionMapper.selectById(id);
        return hwRegion != null ? convertToVo(hwRegion) : null;
    }

    @Override
    public CommonPage<HwRegionVo> list(HwRegionQueryReqDTO queryReqDTO) {
        QueryWrapper<HwRegion> query = new QueryWrapper<>();
        query.eq(HwRegion.IsDeleted, SystemConfigConstants.NOT_DELETED);
        
        // 条件查询
        if (StrUtil.isNotBlank(queryReqDTO.getName())) {
            query.like(HwRegion.Name, queryReqDTO.getName());
        }
        if (queryReqDTO.getParentId() != null) {
            query.eq(HwRegion.ParentId, queryReqDTO.getParentId());
        }
        if (queryReqDTO.getLevel() != null) {
            query.eq(HwRegion.Level, queryReqDTO.getLevel());
        }
        
        // 排序
        query.orderByAsc(HwRegion.Level, HwRegion.Sort, HwRegion.ID);
        
        // 分页查询
        IPage<HwRegion> page = new Page<>(queryReqDTO.getPageNum(), queryReqDTO.getPageSize());
        IPage<HwRegion> result = hwRegionMapper.selectPage(page, query);
        
        // 转换为VO
        List<HwRegionVo> voList = result.getRecords().stream()
                .map(this::convertToVo)
                .collect(Collectors.toList());
        
        // 手动构建CommonPage
        CommonPage<HwRegionVo> commonPage = new CommonPage<>();
        commonPage.setTotalPage((int) result.getPages());
        commonPage.setPageNum((int) result.getCurrent());
        commonPage.setPageSize((int) result.getSize());
        commonPage.setTotal(result.getTotal());
        commonPage.setList(voList);
        return commonPage;
    }

    @Override
    public List<HwRegionNode> treeList() {
        // 查询所有有效区域
        QueryWrapper<HwRegion> query = new QueryWrapper<>();
        query.eq(HwRegion.IsDeleted, SystemConfigConstants.NOT_DELETED);
        query.orderByAsc(HwRegion.Level, HwRegion.Sort, HwRegion.ID);
        
        List<HwRegion> allRegions = hwRegionMapper.selectList(query);
        
        // 构建树状结构
        List<HwRegionNode> rootNodes = allRegions.stream()
                .filter(region -> region.getParentId() == 0)
                .map(region -> convertToNode(region, allRegions))
                .collect(Collectors.toList());
        
        return rootNodes;
    }

    @Override
    public List<HwRegionVo> getByLevel(Integer level) {
        QueryWrapper<HwRegion> query = new QueryWrapper<>();
        query.eq(HwRegion.Level, level)
             .eq(HwRegion.IsDeleted, SystemConfigConstants.NOT_DELETED);
        query.orderByAsc(HwRegion.Sort, HwRegion.ID);
        
        List<HwRegion> regions = hwRegionMapper.selectList(query);
        return regions.stream()
                .map(this::convertToVo)
                .collect(Collectors.toList());
    }

    @Override
    public List<HwRegionVo> getByParentId(Long parentId) {
        QueryWrapper<HwRegion> query = new QueryWrapper<>();
        query.eq(HwRegion.ParentId, parentId)
             .eq(HwRegion.IsDeleted, SystemConfigConstants.NOT_DELETED);
        query.orderByAsc(HwRegion.Sort, HwRegion.ID);
        
        List<HwRegion> regions = hwRegionMapper.selectList(query);
        return regions.stream()
                .map(this::convertToVo)
                .collect(Collectors.toList());
    }

    @Override
    public List<Long> getChildrenIds(Long regionId) {
        List<Long> result = new ArrayList<>();
        collectChildrenIds(regionId, result);
        return result;
    }

    /**
     * 递归收集子区域ID
     */
    private void collectChildrenIds(Long parentId, List<Long> result) {
        QueryWrapper<HwRegion> query = new QueryWrapper<>();
        query.eq(HwRegion.ParentId, parentId)
             .eq(HwRegion.IsDeleted, SystemConfigConstants.NOT_DELETED);
        
        List<HwRegion> children = hwRegionMapper.selectList(query);
        for (HwRegion child : children) {
            result.add(child.getId());
            collectChildrenIds(child.getId(), result);
        }
    }

    /**
     * 将HwRegion转换为HwRegionNode并设置children属性
     */
    private HwRegionNode convertToNode(HwRegion region, List<HwRegion> allRegions) {
        HwRegionNode node = new HwRegionNode();
        BeanUtils.copyProperties(region, node);
        
        // 统计当前区域的监视点数量
        Long monitoringPointCount = hwMonitoringPointService.countByRegionId(region.getId());
        node.setMonitoringPointCount(monitoringPointCount);
        
        List<HwRegionNode> children = allRegions.stream()
                .filter(child -> child.getParentId().equals(region.getId()))
                .map(child -> convertToNode(child, allRegions))
                .collect(Collectors.toList());
        
        node.setChildren(children);
        return node;
    }

    /**
     * Entity转VO
     */
    private HwRegionVo convertToVo(HwRegion hwRegion) {
        HwRegionVo vo = new HwRegionVo();
        BeanUtils.copyProperties(hwRegion, vo);
        return vo;
    }
}